package com.lekang.service.impl;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import com.lekang.common.core.domain.model.LoginUser;
import com.lekang.common.utils.DateUtils;
import com.lekang.common.utils.SecurityUtils;
import com.lekang.domain.Balance;
import com.lekang.domain.BillDetail;
import com.lekang.domain.CheckInManagement;
import com.lekang.domain.OrderManagement;
import com.lekang.dto.AddBillDto;
import com.lekang.mapper.BalanceMapper;
import com.lekang.mapper.CheckInManagementMapper;
import com.lekang.mapper.OrderManagementMapper;
import com.lekang.service.IBillDetailService;
import com.lekang.service.ITaskGenerationService;
import com.lekang.service.IOrderManagementService;
import com.lekang.util.NumberGenerator;
import io.jsonwebtoken.lang.Assert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.lekang.mapper.BillMapper;
import com.lekang.domain.Bill;
import com.lekang.service.IBillService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 账单Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-10-15
 */
@Service
public class BillServiceImpl implements IBillService
{
    private static final Logger log = LoggerFactory.getLogger(BillServiceImpl.class);
    
    @Autowired
    private BillMapper billMapper;
    
    @Autowired
    private ITaskGenerationService taskGenerationService;
    
    @Autowired
    private CheckInManagementMapper checkInManagementMapper;
    // 新增：注入账单详情Service，用于批量新增详情
    @Autowired
    private IBillDetailService billDetailService;

//    用于月费账单新增
    @Autowired
    private IBillService billService;

    @Autowired
    private BalanceMapper balanceMapper;

    // 注入订单Mapper，用于订单账单生成
    @Autowired
    private OrderManagementMapper orderManagementMapper;

    /**
     * 查询账单
     * 
     * @param id 账单主键
     * @return 账单
     */
    @Override
    public Bill selectBillById(Long id)
    {
        return billMapper.selectBillById(id);
    }

    // 建议添加事务注解，确保预存款和账单状态要么同时成功，要么同时失败
    @Transactional
    @Override
    public String updateBillStatus(Bill bill) {
        // 1. 校验参数：账单ID不能为空
        Long billId = bill.getId();
        String newStatus = bill.getTransactionStatus();
        if (billId == null) {
            return "账单ID不能为空";
        }
        if (newStatus == null || newStatus.trim().isEmpty()) {
            return "交易状态不能为空";
        }

        // 2. 校验账单是否存在
        Bill existBill = billMapper.selectBillById(billId);
        if (existBill == null) {
            return "账单不存在或已删除";
        }

        // 3. 接收本期应付金额（前端已校验，后端可再确认非负）
        BigDecimal currentPayable = bill.getCurrentPayable();
        if (currentPayable == null || currentPayable.compareTo(BigDecimal.ZERO) < 0) {
            return "本期应付金额无效"; // 兜底校验，防止前端校验被绕过
        }

        // 4. 查询预存款记录（增加空指针防护）
        Balance balance = balanceMapper.selectBalanceByElderlyId(existBill.getElderlyId());
        if (balance == null) {
            return "未查询到该老人的预存款记录，无法完成操作";
        }

        // 5. 计算剩余预存款（处理prepaymentBalance为null的情况）
        BigDecimal prepaymentBalance = balance.getPrepaymentBalance();
        if (prepaymentBalance == null) {
            prepaymentBalance = BigDecimal.ZERO; // 默认为0，避免null导致的运算错误
        }
        BigDecimal newDepositBalance = prepaymentBalance.subtract(currentPayable);

        // 6. 前端已校验金额足够，但后端仍建议加一层（防止前端校验被绕过）
        if (newDepositBalance.compareTo(BigDecimal.ZERO) < 0) {
            return "预存款余额不足，操作失败";
        }

        // 7. 更新预存款
        balance.setPrepaymentBalance(newDepositBalance);
        int balanceRows = balanceMapper.updateBalance(balance);
        if (balanceRows <= 0) { // 校验预存款是否更新成功
            return "预存款更新失败，请重试";
        }

        // 8. 更新账单状态
        int billRows = billMapper.updateStatusById(billId, newStatus);
        if (billRows <= 0) {
            // 由于加了@Transactional，此处失败会自动回滚预存款的更新
            return "账单状态修改失败，请重试";
        }

        return "success";
    }
    /**
     * 查询账单列表
     * 
     * @param bill 账单
     * @return 账单
     */
    @Override
    public List<Bill> selectBillList(Bill bill)
    {
        return billMapper.selectBillList(bill);
    }

    /**
     * 新增账单
     * 
     * @param bill 账单
     * @return 结果
     */
    @Override
    public int insertBill(Bill bill)
    {
        bill.setCreateTime(DateUtils.getNowDate());
        return billMapper.insertBill(bill);
    }

    /**
     * 修改账单
     * 
     * 说明：
     * 1. 如果是费用账单且交易状态发生变化，会同步更新关联的订单状态
     * 2. 使用事务保证数据一致性
     *
     * @param bill 账单
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateBill(Bill bill)
    {
        try {
            // 1. 查询原账单信息（用于判断状态是否变化）
            Bill oldBill = billMapper.selectBillById(bill.getId());
            String oldTransactionStatus = oldBill != null ? oldBill.getTransactionStatus() : null;
            String newTransactionStatus = bill.getTransactionStatus();

            // 2. 更新账单
            int result = billMapper.updateBill(bill);

            // 3. 如果是费用账单且交易状态发生变化，同步更新关联的订单状态
            if (result > 0 && oldBill != null && "费用账单".equals(oldBill.getBillType())
                && newTransactionStatus != null && !newTransactionStatus.equals(oldTransactionStatus)) {

                log.info("费用账单ID: {} 交易状态从 {} 变更为 {}，开始同步更新订单状态",
                    bill.getId(), oldTransactionStatus, newTransactionStatus);

                String billNo = bill.getBillNo();
                if (billNo == null && oldBill != null) {
                    billNo = oldBill.getBillNo();
                }

                if (billNo != null) {
                    // 注意：这里需要注入IOrderManagementService
                    // 为了避免循环依赖，我们需要使用特殊的处理方式
                    // 暂时通过ApplicationContext获取bean
                    try {
                        IOrderManagementService orderService = com.lekang.common.utils.spring.SpringUtils
                            .getBean(IOrderManagementService.class);
                        orderService.updateOrderStatusByBillStatus(billNo, newTransactionStatus);
                        log.info("费用账单ID: {} 关联的订单状态同步完成", bill.getId());
                    } catch (Exception e) {
                        log.warn("同步更新订单状态失败，但账单更新成功: {}", e.getMessage());
                        // 不抛出异常，避免回滚账单更新
                    }
                }
            }

            return result;
        } catch (Exception e) {
            log.error("更新账单失败，账单ID: {}", bill.getId(), e);
            throw e;
        }
    }

    /**
     * 批量删除账单
     * 
     * @param ids 需要删除的账单主键
     * @return 结果
     */
    @Override
    public int deleteBillByIds(Long[] ids)
    {
        return billMapper.deleteBillByIds(ids);
    }

    /**
     * 删除账单信息
     * 
     * @param id 账单主键
     * @return 结果
     */
    @Override
    public int deleteBillById(Long id)
    {
        return billMapper.deleteBillById(id);
    }

    // 新增：实现根据老人ID查询账单列表
    @Override
    public List<Bill> selectBillListByElderlyId(Long elderlyId) {
        // 直接调用Mapper中新增的方法
        return billMapper.selectBillListByElderlyId(elderlyId);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addBillWithDetails(AddBillDto addBillDto)
    {
        // -------------------------- 1. 新增账单主表 --------------------------
        Bill bill = new Bill();
        // 1.1 复制DTO字段到Bill实体（新增：接收前端传递的creator）
        bill.setBillNo(addBillDto.getBillNo());
        bill.setBillType(addBillDto.getBillType());
        bill.setBillMonth(addBillDto.getBillMonth());
        bill.setElderlyId(addBillDto.getElderlyId());
        bill.setPaymentDeadline(addBillDto.getPaymentDeadline());
        bill.setPaymentChannel(addBillDto.getPaymentChannel());
        bill.setPaymentMethod(addBillDto.getPaymentMethod());
        bill.setPaymentRemark(addBillDto.getPaymentRemark());
        bill.setPrepaymentAmount(addBillDto.getPrepaymentAmount());
        //添加账单开始日期和结束日期
        bill.setBillStartTime(addBillDto.getBillStartTime());
        bill.setBillEndTime(addBillDto.getBillEndTime());
        // 关键修改1：从DTO获取creator（前端传递的创建人ID），不再后端获取
        bill.setCreator(addBillDto.getCreator());
        bill.setCreateTime(new Date()); // 创建时间仍后端自动填充（也可前端传，按需调整）

        // 3. 计算添加项和扣减项总和（原有逻辑）
        List<BillDetail> detailList = addBillDto.getBillDetails();
        if (detailList == null || detailList.isEmpty()) {
            throw new RuntimeException("账单详情不能为空");
        }
        BigDecimal totalAdd = BigDecimal.ZERO;
        BigDecimal totalDeduct = BigDecimal.ZERO;
        for (BillDetail detail : detailList) {
            BigDecimal amount = Objects.isNull(detail.getAmount()) ? BigDecimal.ZERO : detail.getAmount();
            if ("添加项".equals(detail.getType())) {
                totalAdd = totalAdd.add(amount);
            } else if ("扣减项".equals(detail.getType())) {
                totalDeduct = totalDeduct.add(amount);
            }
        }

        // 4. 计算每月应付总金额（全月费用）
        BigDecimal monthlyPayable = totalAdd.subtract(totalDeduct);
        if (monthlyPayable.compareTo(BigDecimal.ZERO) < 0) {
            throw new RuntimeException("扣减金额不能超过添加金额，总金额不能为负");
        }

// 5. 处理时间解析（确保时间不为null）
        Date startTime = bill.getBillStartTime();
        Date endTime = bill.getBillEndTime();
        if (startTime == null || endTime == null) {
            throw new RuntimeException("账单开始时间或结束时间不能为空");
        }
        if (endTime.before(startTime)) {
            throw new RuntimeException("账单结束时间不能早于开始时间");
        }

// 5.1 初始化日历（仅保留年月日）
        Calendar startCal = Calendar.getInstance();
        startCal.setTime(startTime);
        startCal.set(Calendar.HOUR_OF_DAY, 0);
        startCal.set(Calendar.MINUTE, 0);
        startCal.set(Calendar.SECOND, 0);
        startCal.set(Calendar.MILLISECOND, 0);

        Calendar endCal = Calendar.getInstance();
        endCal.setTime(endTime);
        endCal.set(Calendar.HOUR_OF_DAY, 0);
        endCal.set(Calendar.MINUTE, 0);
        endCal.set(Calendar.SECOND, 0);
        endCal.set(Calendar.MILLISECOND, 0);

// 6. 确定当前所在月（以开始时间的月份为准）
        int currentMonth = startCal.get(Calendar.MONTH);
        int currentYear = startCal.get(Calendar.YEAR);

// 6.1 计算当前月的总天数
        int daysInCurrentMonth = startCal.getActualMaximum(Calendar.DAY_OF_MONTH);

// 6.2 确定本期在当前月内的实际天数（跨月则只算到当月月底）
        Calendar actualEndCal = (Calendar) endCal.clone();
// 若结束时间不在当前月，将实际结束日设为当月最后一天
        if (actualEndCal.get(Calendar.YEAR) != currentYear || actualEndCal.get(Calendar.MONTH) != currentMonth) {
            actualEndCal.set(currentYear, currentMonth, daysInCurrentMonth); // 当月最后一天
        }

// 计算当前月内的天数（包含首尾）
        long timeDiff = actualEndCal.getTimeInMillis() - startCal.getTimeInMillis();
        int currentDays = (int) (timeDiff / (1000 * 60 * 60 * 24)) + 1;
        if (currentDays <= 0) {
            throw new RuntimeException("当前月内的账单周期无效");
        }

// 7. 计算本期应付金额（仅当前月内的费用）
        BigDecimal dailyRate = monthlyPayable.compareTo(BigDecimal.ZERO) == 0
                ? BigDecimal.ZERO
                : monthlyPayable.divide(new BigDecimal(daysInCurrentMonth), 4, BigDecimal.ROUND_HALF_UP);
        BigDecimal currentPayable = dailyRate.multiply(new BigDecimal(currentDays))
                .setScale(2, BigDecimal.ROUND_HALF_UP);

// 8. 校验（理论上不会超，保险起见）
        if (currentPayable.compareTo(monthlyPayable) > 0) {
            throw new RuntimeException("本期应付金额不能超过全月应付金额");
        }

// 9. 赋值金额字段
        bill.setBillAmount(monthlyPayable);
        bill.setMonthlyPayable(monthlyPayable);
        bill.setCurrentPayable(currentPayable);
        bill.setPayableAmount(currentPayable);

        // 1.4 插入主表（逻辑不变）
        int billInsertResult = billMapper.insertBill(bill);
        if (billInsertResult != 1) {
            throw new RuntimeException("账单主表新增失败");
        }
        Long billId = bill.getId();


        // -------------------------- 2. 批量新增账单详情（逻辑不变） --------------------------
        for (BillDetail detail : detailList) {
            detail.setBillId(billId);
        }

        int detailInsertResult = billDetailService.batchInsertBillDetails(detailList);
        if (detailInsertResult != detailList.size()) {
            throw new RuntimeException("账单详情批量新增失败（部分或全部未插入）");
        }


        // 关键修改2：删除后端获取当前用户ID的工具方法（getCurrentUserId()）
        // （因为不再使用，留着会冗余，直接删除即可）
        
        
        // ========== 新增：入住首月账单生成后，自动生成护理任务 ==========
        try {
            // 判断是否是入住首月账单（通过 relatedOrder 关联入住单号）
            String relatedOrder = addBillDto.getRelatedOrder();
            if (relatedOrder != null && !relatedOrder.trim().isEmpty()) {
                log.info("检测到入住首月账单，关联订单号: {}，开始生成护理任务...", relatedOrder);
                
                // 通过入住单号查询入住记录
                CheckInManagement checkIn = checkInManagementMapper.selectCheckInManagementByCheckInNo(relatedOrder);
                if (checkIn != null && checkIn.getId() != null) {
                    // 调用任务生成服务
                    int taskCount = taskGenerationService.generateFirstMonthTasks(checkIn.getId());
                    log.info("入住首月任务生成成功！入住ID: {}, 老人ID: {}, 生成任务数量: {}", 
                        checkIn.getId(), checkIn.getElderlyId(), taskCount);
                } else {
                    log.warn("未找到关联的入住记录，入住单号: {}，跳过任务生成", relatedOrder);
                }
            }
        } catch (Exception e) {
            // 任务生成失败不影响账单保存，仅记录日志
            log.error("入住首月任务生成失败，但账单已保存成功。错误信息: {}", e.getMessage(), e);
            // 注意：这里不抛出异常，避免回滚账单事务
        }


        return true;
    }

    // 处理"YYYY-MM"格式，返回减去一个月后的同格式字符串
    public static String subtractOneMonth(String billMonth) {
        try {
            // 定义日期格式（匹配"YYYY-MM"）
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");

            // 1. 解析字符串为YearMonth对象
            YearMonth yearMonth = YearMonth.parse(billMonth, formatter);

            // 2. 减去一个月
            YearMonth previousMonth = yearMonth.minusMonths(1);

            // 3. 格式化回"YYYY-MM"字符串
            return previousMonth.format(formatter);

        } catch (DateTimeParseException e) {
            // 处理格式错误（如输入不是"YYYY-MM"）
            System.err.println("输入格式错误，必须是'YYYY-MM'格式：" + e.getMessage());
            return null; // 或根据业务需求抛出异常
        }
    }

    /**
     * 使用Java 8 Time API的实现（推荐）
     */
    public static Date[] getMonthStartAndEndDatesJava8(String billMonth) {
        try {
            // 解析月份
            java.time.YearMonth yearMonth = java.time.YearMonth.parse(billMonth);

            // 获取本月第一天8点
            java.time.LocalDateTime firstDay8am = yearMonth.atDay(1).atTime(8, 0, 0);
            Date firstDate = java.util.Date.from(firstDay8am.atZone(java.time.ZoneId.systemDefault()).toInstant());

            // 获取本月最后一天8点
            java.time.LocalDateTime lastDay8am = yearMonth.atEndOfMonth().atTime(8, 0, 0);
            Date lastDate = java.util.Date.from(lastDay8am.atZone(java.time.ZoneId.systemDefault()).toInstant());

            return new Date[]{firstDate, lastDate};

        } catch (Exception e) {
            throw new IllegalArgumentException("月份格式错误，应为'yyyy-MM'格式，例如：'2025-11'", e);
        }
    }

    //此刻年月
    public static String getCurrentYearMonth() {
        // 1. 获取当前日期（默认使用系统时区，建议显式指定时区避免差异）
        // 如需要北京时间，可使用 ZoneId.of("Asia/Shanghai")
        LocalDate currentDate = LocalDate.now(ZoneId.systemDefault());

        // 2. 定义格式化器，指定输出格式为 "yyyy-MM"
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");

        // 3. 格式化当前日期，仅保留年和月
        return currentDate.format(formatter);
    }

    @Override
    public boolean addBillWithBillDetails(AddBillDto addBillDto,String isAuto ) {
        NumberGenerator numberGenerator = new NumberGenerator();
        String billNo = numberGenerator.numberGeneration("BL");
//        System.out.println(addBillDto.getCreator());
        Bill bill1 = new Bill();
        bill1.setBillType(addBillDto.getBillType());
        bill1.setElderlyId(addBillDto.getElderlyId());
        //处理日期字符串
        String month = getCurrentYearMonth();
        //手动生成上个月用来查询
        if (isAuto!=null){
            bill1.setBillMonth(subtractOneMonth(month));
        }else {
            //当月数据
            bill1.setBillMonth(getCurrentYearMonth());
        }


        System.out.println(month+"月份");
//        System.out.println(bill1+"数据");
            List<Bill> bills = billService.selectBillList(bill1);
        if (bills == null || bills.isEmpty()) {
            // 处理空集合情况（如抛异常、打印日志、返回失败等）
            throw new RuntimeException("未查询到对应账单数据，无法执行操作");
            // 或：
            // System.err.println("未查询到对应账单数据");
            // return false;
        }
            Bill bill = bills.get(0);
            bill.setBillMonth(addBillDto.getBillMonth());
            bill.setBillNo(addBillDto.getBillNo());
            bill.setId(null);
            //创建人
            bill.setCreator(addBillDto.getCreator());
//            手动生成
            bill.setExtraField1("手动生成");

//            自动或手动一个的应付金额是一样的
        bill.setCurrentPayable(bill.getMonthlyPayable());
        bill.setPayableAmount(bill.getMonthlyPayable());
//            如果自动创建创建人id为
        if(isAuto!=null){
            bill.setBillMonth(getCurrentYearMonth());
            bill.setBillNo(billNo);
            bill.setExtraField1("系统生成");
        }



            bill.setPaymentChannel(null);
            bill.setPaymentMethod(null);
            bill.setPaymentRemark(null);
            bill.setCreateTime(new Date());

//        交易状态为未支付
            bill.setTransactionStatus("0");
            //截止日期
//            System.out.println(bill);
            bill.setPaymentDeadline(getMonthStartAndEndDatesJava8(bill.getBillMonth())[1]);
            bill.setBillStartTime(getMonthStartAndEndDatesJava8(bill.getBillMonth())[0]);
            bill.setBillEndTime(getMonthStartAndEndDatesJava8(bill.getBillMonth())[1]);


//            System.out.println(bill);

            List<BillDetail> detailList = bill.getBillDetails();
            if (detailList == null || detailList.isEmpty()) {
                throw new RuntimeException("账单详情不能为空");
            }

//        // 1.4 插入主表（逻辑不变）
            int billInsertResult = billMapper.insertBill(bill);
            if (billInsertResult != 1) {
                throw new RuntimeException("账单主表新增失败");
            }
            Long billId = bill.getId();


            // -------------------------- 2. 批量新增账单详情（逻辑不变） --------------------------
            for (BillDetail detail : detailList) {
                detail.setId(null);
                detail.setBillId(billId);
            }

            int detailInsertResult = billDetailService.batchInsertBillDetails(detailList);
            if (detailInsertResult != detailList.size()) {
                throw new RuntimeException("账单详情批量新增失败（部分或全部未插入）");
            }




        return true;
    }

    /**
     * 根据订单生成费用账单
     *
     * 说明：
     * 1. 当系统生成订单后，自动将订单转成账单
     * 2. 订单与账单的对应规则是1:1，每一笔订单都会生成账单
     * 3. 订单与账单的对应关系：
     *    - 订单状态"待支付" -> 账单状态"待支付"
     *    - 订单状态"待执行、已执行、已完成" -> 账单状态"已支付"
     *    - 订单状态"已关闭、已退款" -> 账单状态"已关闭"
     *
     * @param orderId 订单ID
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean generateBillForOrder(Long orderId) {
        try {
            log.info("开始为订单ID: {} 生成费用账单", orderId);

            // 1. 查询订单信息
            OrderManagement order = orderManagementMapper.selectOrderManagementById(orderId);
            if (order == null) {
                log.warn("订单ID: {} 不存在，无法生成账单", orderId);
                return false;
            }

            // 2. 创建账单对象
            Bill bill = new Bill();

            // 2.1 生成账单编号
            NumberGenerator numberGenerator = new NumberGenerator();
            String billNo = numberGenerator.numberGeneration("BL");
            bill.setBillNo(billNo);

            // 2.2 设置账单基本信息
            bill.setBillType("费用账单");
            bill.setBillMonth(getCurrentYearMonth());
            bill.setElderlyId(order.getElderlyId());
            bill.setCreator(order.getOrderUserId());
            bill.setCreateTime(new Date());

            // 2.3 关联订单编号
            bill.setRelatedOrder(order.getOrderNo());

            // 2.4 设置金额（订单金额即为账单金额）
            bill.setBillAmount(order.getOrderAmount());
            bill.setMonthlyPayable(order.getOrderAmount());
            bill.setCurrentPayable(order.getOrderAmount());
            bill.setPayableAmount(order.getOrderAmount());
            bill.setPrepaymentAmount(BigDecimal.ZERO);

            // 2.5 设置账单时间（当月）
            Date[] monthDates = getMonthStartAndEndDatesJava8(getCurrentYearMonth());
            bill.setBillStartTime(monthDates[0]);
            bill.setBillEndTime(monthDates[1]);
            bill.setPaymentDeadline(monthDates[1]);

            // 2.6 根据订单状态设置账单交易状态
            String transactionStatus = getTransactionStatusByOrderStatus(order.getOrderStatus());
            bill.setTransactionStatus(transactionStatus);

            // 2.7 设置额外标识
            bill.setExtraField1("订单生成");

            // 3. 插入账单主表
            int billInsertResult = billMapper.insertBill(bill);
            if (billInsertResult != 1) {
                throw new RuntimeException("账单主表新增失败");
            }
            Long billId = bill.getId();

            // 4. 创建账单详情（单条明细）
            BillDetail detail = new BillDetail();
            detail.setBillId(billId);
            detail.setType("添加项");

            // 获取护理项目名称作为项目名称
            String itemName = "订单费用";
            if (order.getNursingItem() != null && order.getNursingItem().getName() != null) {
                itemName = order.getNursingItem().getName();
            }
            detail.setItemName(itemName);
            detail.setServiceContent("订单编号：" + order.getOrderNo());
            detail.setAmount(order.getOrderAmount());

            // 5. 插入账单详情
            List<BillDetail> detailList = new java.util.ArrayList<>();
            detailList.add(detail);
            int detailInsertResult = billDetailService.batchInsertBillDetails(detailList);
            if (detailInsertResult != detailList.size()) {
                throw new RuntimeException("账单详情新增失败");
            }

            log.info("订单ID: {} 费用账单生成成功，账单编号: {}", orderId, billNo);
            return true;

        } catch (Exception e) {
            log.error("为订单ID: {} 生成费用账单失败", orderId, e);
            throw e;
        }
    }

    /**
     * 根据订单状态更新关联的费用账单状态
     *
     * 说明：
     * 1. 当订单状态改变时，同步更新对应的费用账单状态
     * 2. 通过订单编号查找关联的费用账单
     * 3. 根据订单状态映射对应的账单交易状态
     *
     * @param orderNo 订单编号
     * @param orderStatus 订单状态
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateBillStatusByOrderStatus(String orderNo, Long orderStatus) {
        try {
            log.info("开始根据订单编号: {} 更新费用账单状态，订单状态: {}", orderNo, orderStatus);

            // 1. 查询关联的费用账单
            Bill queryBill = new Bill();
            queryBill.setRelatedOrder(orderNo);
            queryBill.setBillType("费用账单");

            List<Bill> billList = billMapper.selectBillList(queryBill);
            if (billList == null || billList.isEmpty()) {
                log.warn("未找到订单编号: {} 关联的费用账单", orderNo);
                return false;
            }

            // 2. 获取映射后的账单交易状态
            String newTransactionStatus = getTransactionStatusByOrderStatus(orderStatus);

            // 3. 更新每个关联的费用账单状态
            for (Bill bill : billList) {
                // 只有状态发生变化时才更新，避免不必要的操作
                if (!newTransactionStatus.equals(bill.getTransactionStatus())) {
                    Bill updateBill = new Bill();
                    updateBill.setId(bill.getId());
                    updateBill.setTransactionStatus(newTransactionStatus);

                    int result = billMapper.updateBill(updateBill);
                    if (result > 0) {
                        log.info("费用账单ID: {} 状态已更新为: {}", bill.getId(), newTransactionStatus);
                    }
                } else {
                    log.debug("费用账单ID: {} 状态未发生变化，跳过更新", bill.getId());
                }
            }

            return true;

        } catch (Exception e) {
            log.error("根据订单编号: {} 更新费用账单状态失败", orderNo, e);
            throw e;
        }
    }

    /**
     * 根据订单状态获取账单交易状态
     *
     * @param orderStatus 订单状态
     * @return 账单交易状态
     */
    private String getTransactionStatusByOrderStatus(Long orderStatus) {
        if (orderStatus == null) {
            return "0"; // 默认未支付
        }

        // 订单状态对应关系：
        // 0-待支付 -> 账单状态 0-待支付
        // 1-待执行、2-已执行、3-已完成 -> 账单状态 1-已支付
        // 4-已退款、5-已关闭 -> 账单状态 2-已关闭

        if (orderStatus.equals(0L)) {
            return "0"; // 待支付
        } else if (orderStatus.equals(1L) || orderStatus.equals(2L) || orderStatus.equals(3L)) {
            return "1"; // 已支付
        } else if (orderStatus.equals(4L) || orderStatus.equals(5L)) {
            return "2"; // 已关闭
        }

        return "0"; // 默认未支付
    }
}
